import React from 'react';
import { withLeaflet, GeoJSON } from 'react-leaflet';
import axios from 'axios';
import { isEmpty, isEqual } from 'lodash';
import setting from './setting';

const locationOrigin = window.location.origin;
const CHINA_JSON_BASE_URL = `${locationOrigin}/geojson`;

function formatAdCode(adcode) {
  switch (adcode) {
    case 110000: // 北京
      return 110100;
    case 500000: // 重庆
      return 500100;
    case 120000: // 天津
      return 120100;
    case 310000: // 天津
      return 310100;
    default:
      return adcode;
  }
}

// 区域联动层，默认中国地图
class LGeoJsonLayer extends React.Component {
  static setting = setting;

  parentInfo = []; // 记录上层编码和边界信息

  constructor(props) {
    super(props);
    this.state = {
      currentFloor: 0, // 当前下钻层级
      curGeoData: null, // 当前展示区域的geoJson数据
      isBottom: false // 是否下钻到最底部
    };

    let defaultValue = props.events.click.fields.adcode.value;
    defaultValue = defaultValue || 100000;

    this.setDataPool(defaultValue);
  }

  componentDidMount() {
    this.getGeoDataByCode(100000).then((data) => {
      this.setState({
        curGeoData: data
      });
    });
  }

  componentWillReceiveProps(nextProps) {
    const { data } = this.props;
    const { data: nextData } = nextProps;

    if (nextData && nextData.length > 0 && !isEqual(data, nextProps.data)) {
      const { adcode } = nextData[0];
      this.setDataPool(adcode);
      this.updateEventsDefaultValue(adcode);
    }
  }

  // 返回上层按钮样式设置
  get buttonStyle() {
    const { config: { button } } = this.props;
    if (!button) return {};

    const { backgroundColor, font } = button;
    return {
      backgroundColor,
      ...font
    };
  }

  // 提示框设置
  get tooltip() {
    const {
      config: {
        tooltip: {
          show, borderColor, borderWidth, font,
          background: { type: backgroundType, backgroundColor, imageUrl }
        }
      }
    } = this.props;
    return {
      show,
      borderColor,
      borderWidth,
      font,
      backgroundType,
      backgroundColor,
      imageUrl
    };
  }

  get baseStyle() {
    const { config: { base } } = this.props;

    return base;
  }

  // 获得区域颜色
  getSpotColor = (adcode) => {
    const { data } = this.props;
    const { colors } = this.baseStyle;
    if (isEmpty(data)) return colors[0].color;

    let value = 0;
    const itemData = this.geDatabyCode(adcode);
    if (itemData) {
      value = Number(itemData.value) || 0;
    }

    const set = colors.reduce((pre, item) =>
      (item.start < value && value <= item.end ? item.color : pre), null);
    return set || colors[0].color;
  };

  // 获得区域样式
  getGeoStyle = (feature) => {
    const { color, weight } = this.baseStyle;

    return {
      color,
      weight,
      opacity: 1,
      fillOpacity: 1,
      fillColor: this.getSpotColor(feature.properties.adcode)
    };
  };

  // 获得弹窗内容
  getPopupContent = (info) => {
    const {
      borderColor, borderWidth, font, backgroundType, backgroundColor, imageUrl
    } = this.tooltip;
    const myBackground = backgroundType === 'color'
      ? `background-color: ${backgroundColor}` : `background-image: url(${imageUrl})`;


    const infoArray = `${info}`.split(';');
    const text = infoArray.join('<br />');

    return `<div class="map-marker-content" style="${myBackground};
      border: ${borderWidth}px solid ${borderColor};
      color: ${font.color};
      font-size: ${font.fontSize}px;
      font-family: ${font.fontFamily};
      font-weight: ${font.fontWeight};">
     ${text}
    </div>`;
  };

  isDownable = (level) => {
    const { floor } = this.baseStyle;
    switch (floor) {
      case 'province':
        return;
      case 'city':
        if (level === 'city' || level === 'district') {
          return;
        }
        break;
      case 'district':
        if (level === 'district') {
          return;
        }
        break;
      default:
        break;
    }

    // 区域下钻
    const { isBottom } = this.state;
    if (isBottom) return;
    return true;
  }

  onEachFeature = (feature, layer) => {
    const { show } = this.tooltip;
    const { adcode, parent, level } = feature.properties;
    const itemData = this.geDatabyCode(adcode);

    // 区域弹窗
    if (show !== 'hide') {
      const popupContent = this.getPopupContent((itemData && itemData.tooltip) || feature.properties.name);

      layer.bindTooltip(popupContent, {
        permanent: show === 'always',
        className: 'marker-tooltip'
      });
    }


    layer.on('click', async () => {
      const { leaflet: { map } } = this.props;

      this.setDataPool(adcode);

      if (!this.isDownable(level)) return; // 不能下钻即返回

      await this.getGeoDataByCode(adcode, level).then((data) => {
        const { currentFloor } = this.state;
        const hasNext = level === 'district' || Number(adcode) === 710000;

        this.setState({
          curGeoData: data,
          currentFloor: currentFloor + 1,
          isBottom: hasNext
        });

        this.parentInfo.push({
          adcode: parent.adcode,
          bounds: map.getBounds()
        });

        map.fitBounds(layer.getBounds());
      });
    });
  };

  // 点击返回上层
  onClickTop = async () => {
    const { leaflet: { map } } = this.props;
    const parentLayer = this.parentInfo.pop();

    await this.getGeoDataByCode(parentLayer.adcode).then((data) => {
      const { currentFloor } = this.state;

      this.setState({
        curGeoData: data,
        currentFloor: currentFloor - 1,
        isBottom: false
      });
      this.setDataPool(parentLayer.adcode);

      map.fitBounds(parentLayer.bounds);
    }).catch(() => {
      this.parentInfo.push(parentLayer);
    });
  };

  // 通过区域编码获得geoJson
  getGeoDataByCode(code, level) {
    const base = CHINA_JSON_BASE_URL;
    // 最深层级到三级县
    const adcode = formatAdCode(code);
    const url = level === 'district'
      ? `${base}/${adcode}.json`
      : `${base}/${adcode}_full.json`;

    return new Promise((resolve, reject) => {
      axios({
        method: 'get',
        url,
        headers: {
          'cityos-application-code': 'imonet'
        }
      })
        .then((response) => {
          resolve(response.data);
        }, (error) => {
          reject(error);
        });
    });
  }

  // 更新data poll变量池
  setDataPool(value) {
    const {
      bigScreen: { setDataPool },
      events: { click }, path, editable
    } = this.props;

    const dataPoll = { adcode: value };
    setDataPool(click, dataPoll, path, editable);
  }

  geDatabyCode = (adcode) => {
    const { data } = this.props;
    const code = Number(adcode);

    return data.find(item => Number(item.adcode) === code);
  };

  // 更新交互事件绑定的默认值
  updateEventsDefaultValue(value) {
    const {
      bigScreen: { updateEventsDefaultValue }, path, editable
    } = this.props;

    if (!editable) return;

    updateEventsDefaultValue(path, { 'click.fields.adcode.value': value });
  }


  render() {
    const { data } = this.props;
    if (isEmpty(data)) return null;

    const { curGeoData, currentFloor } = this.state;
    return (
      <React.Fragment>
        <GeoJSON
          key={Math.floor(Math.random() * 100)}
          data={curGeoData}
          style={(feature) => this.getGeoStyle(feature)}
          onEachFeature={this.onEachFeature}
        />
        {currentFloor !== 0
        && <div
          className="leaflet-map-geo-heat-btn"
          style={this.buttonStyle}
          onClick={this.onClickTop}
        >
          返回上层
        </div>}
      </React.Fragment>
    );
  }
}

export default withLeaflet(LGeoJsonLayer);
